package com.feige.core.context;

import com.feige.auth.pojo.IUser;
import com.feige.auth.pojo.LoginUser;
import com.feige.jwt.TokenHelper;
import com.feige.web.handler.HttpHandler;
import lombok.NonNull;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.ResolvableType;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @author feige<br />
 * @ClassName: AppContext <br/>
 * @Description: <br/>
 * @date: 2022/12/4 21:12<br/>
 */
@Component
public class AppContext implements ApplicationContextAware {

    private static ApplicationContext ac;

    @Override
    public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
        ac = applicationContext;
    }



    public static Object getBean(String name) throws BeansException {
        return ac.getBean(name);
    }

    public static <T> T getBean(String name, Class<T> clazz) throws BeansException{
        return ac.getBean(name, clazz);
    }

    public static Object getBean(String name, Object... objs) throws BeansException{
        return ac.getBean(name, objs);
    }

    public static <T> T getBean(Class<T> clazz) throws BeansException{
        return ac.getBean(clazz);
    }

    public static <T> T getBean(Class<T> clazz, Object... objs) throws BeansException{
        return ac.getBean(clazz, objs);
    }

    public static <T> ObjectProvider<T> getBeanProvider(Class<T> clazz){
        return ac.getBeanProvider(clazz);
    }

    public static <T> ObjectProvider<T> getBeanProvider(ResolvableType rt){
        return ac.getBeanProvider(rt);
    }

    public static boolean containsBean(String name){
        return ac.containsBean(name);
    }

    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException{
        return ac.isSingleton(name);
    }

    public static boolean isPrototype(String name) throws NoSuchBeanDefinitionException{
        return ac.isPrototype(name);
    }

    public static boolean isTypeMatch(String name, ResolvableType rt) throws NoSuchBeanDefinitionException{
        return ac.isTypeMatch(name, rt);
    }

    public static boolean isTypeMatch(String name, Class<?> clazz) throws NoSuchBeanDefinitionException{
        return ac.isTypeMatch(name, clazz);
    }

    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException{
        return ac.getType(name);
    }

    public static Class<?> getType(String name, boolean b) throws NoSuchBeanDefinitionException{
        return ac.getType(name, b);
    }

    public static String[] getAliases(String name){
        return ac.getAliases(name);
    }

    public static Long currentLoginUserId(){
        return MapUtils.getLong(currentUserMap(), IUser.ID);
    }

    public static String currentLoginName(){
        return MapUtils.getString(currentUserMap(), IUser.LOGIN_NAME);
    }

    public static Long currentUserId(){
        return MapUtils.getLong(currentUserMap(), IUser.USER_ID);
    }

    public static Map<String, Object> currentUserMap(){
        TokenHelper tokenHelper = getBean(TokenHelper.class);
        return tokenHelper.getClaims(HttpHandler.getRequest());
    }

    public static IUser buildUser(Function<Map<String, Object>, IUser> fun){
        return fun.apply(currentUserMap());
    }

    public static IUser currentLoginUser(){
        return buildUser(LoginUser::new);
    }
}
